
import schema from 'async-validator';
import { errLogger } from 'ROOT/common/logger';
import { AppContext } from 'ROOT/interface/App';
import { traderRobot } from 'ROOT/TraderRobot';
import TradeAccountService from '../trade-account/TradeAccount.service';
import SymbolOrderConfigService from '../symbol-order-config/SymbolOrderConfig.service';
import { BinanceTrader, binancePriceConverter } from 'ROOT/binance/BinanceTrader';
import { binanceCommon } from 'ROOT/binance/BinanceCommon';
import { PositionSide, numberInString } from 'binance';
import { parserBaseSymbol, parserQuoteSymbol } from 'ROOT/trader';
import * as AutoOrderHistoryService from '../order-history/AutoOrderHistory.service';
import { cryptoHelper } from 'ROOT/utils/crypto';
import { autoToFixed } from 'ROOT/utils';

export interface MixPosition {
  entryPrice?: numberInString;
  positionAmt?: numberInString;
  symbol: string;
  unRealizedProfit?: numberInString;
  positionSide?: PositionSide;
  amount?: number;
}
export default class ExchangeController {
  public static async assetTransfer(ctx: AppContext) {
    const body = ctx.request.body as Record<string, any>;
    const validator = new schema({
      asset: {
        type: "string",
        required: true
      },
      type: {
        type: "string",
        required: true
      },
      amount: {
        type: "number",
      }
    });
    try {
      await validator.validate(body);
    } catch ({ errors, fields }) {
      ctx.sendError({ errors });
      return;
    }

    const userId = ctx.state.user && ctx.state.user.id;
    const userTrader = traderRobot.trader.findUserTrader(userId);
    if (!userTrader) {
      return ctx.sendError({message: `findUserTrader(${userId})`});
    }

    try {
     
      await userTrader.assetTransfer({
        asset: body.asset,
        type: body.type,
        amount: body.amount,
      })
      return ctx.sendSuccess({});
    } catch (error) {
      ctx.sendError({ message: error });
    }
  }

  public static async getAsset(ctx: AppContext) {
    const query = ctx.request.query as Record<string, any>;
    const validator = new schema({
      id: {
        type: "number",
        // required: true
      },
      from: {
        type: "string",
        required: true
      },

    });

    try {
      await validator.validate({ from: query.from });
    } catch ({ errors, fields }) {
      ctx.sendError({ errors });
      return;
    }

    const userId = ctx.state.user && ctx.state.user.id;
    const exchangeAccount = await TradeAccountService.findOne({userid: userId}, true)
    if (!exchangeAccount) {
      return ctx.sendError({message: `账户未找到，或者配置错误 ${userId}`});
    }

    try {

      if (exchangeAccount.access_key) {
        try {
          exchangeAccount.access_key = cryptoHelper.decrypt(exchangeAccount.access_key)
          exchangeAccount.secret_key = cryptoHelper.decrypt(exchangeAccount.secret_key)
        } catch (error) {
          console.error(error)
        }
      }

      if (exchangeAccount.exchange === 'binance') {
        const exchangeTrader = new BinanceTrader(userId, binanceCommon,{
          access_key: exchangeAccount.secret_key,
          secret_key: exchangeAccount.access_key,
          username: '1111'
        });
        if (query.from === 'MAIN') {
          const list = await exchangeTrader.mainClient.getBalances()
          const options  = list.filter(item => Number(item.free ) > 0).map(item => {
            return {
              asset: item.coin,
              availableBalance: item.free,
            }
          })
          exchangeTrader.destroy();
          return ctx.sendSuccess({data: options});
        } else if (query.from === 'UMFUTURE') {
          const list = await exchangeTrader.futureClient.getBalance();
          
          const options  = list.filter(item => Number(item.availableBalance ) > 0).map(item => {
            return item
          })
          exchangeTrader.destroy();
          return ctx.sendSuccess({data: options });
        } else if (query.from === 'CMFUTURE') {
          const list = await exchangeTrader.deliveryClient.getBalance();
          const options = list.filter(item => Number(item.availableBalance ) > 0).map(item => {
            return item
          })
          exchangeTrader.destroy();
          return ctx.sendSuccess({data: options });
        }
      } else {
        return ctx.sendError({ message: `交易所不支持${exchangeAccount.exchange}` });
      }
      ctx.sendError({ message: 'from 参错误' });
    } catch (error) {
      console.log(error)
      ctx.sendError({ message: error.message });
    }
  }
  public static getPositions = async (ctx: AppContext) => {
    const query = ctx.request.query as Record<string, any>;
    const userId = ctx.state.user && ctx.state.user.id;

    const validator = new schema({
      id: {
        type: "string",
        required: true
      },
    });

    try {
      await validator.validate({id: query.id});
    } catch ({ errors, fields }) {
      ctx.sendError({ errors });
      return;
    }
 
    try {
      const symbolOrderConfig = await SymbolOrderConfigService.findOne({id: Number(query.id)})
      const exchangeAccount = await TradeAccountService.findOne({userid: symbolOrderConfig.userid}, true)
      if (!exchangeAccount) {
        return ctx.sendError({message: `账户未找到，或者配置错误 ${userId}`});
      }
      if (exchangeAccount.access_key) {
          exchangeAccount.access_key = cryptoHelper.decrypt(exchangeAccount.access_key)
          exchangeAccount.secret_key = cryptoHelper.decrypt(exchangeAccount.secret_key)
      }

      if (exchangeAccount.exchange === 'binance') {
        const exchangeTrader = new BinanceTrader(userId, binanceCommon,{
          access_key: exchangeAccount.secret_key,
          secret_key: exchangeAccount.access_key,
          username: '1111'
        });
        let data: MixPosition[] = []
        if (symbolOrderConfig.trade_type === 'spot') {
          const balanceMap = await exchangeTrader.getBalance();
          data = [
            {
              symbol: symbolOrderConfig.symbol,
              amount: Number(balanceMap[parserBaseSymbol(symbolOrderConfig.symbol)].free),
            },
            {
              symbol: parserQuoteSymbol(symbolOrderConfig.symbol),
              amount: Number(balanceMap[parserQuoteSymbol(symbolOrderConfig.symbol)].free),
            }
          ]
        } else if (symbolOrderConfig.trade_type === 'futures') {
          const positions = await exchangeTrader.getFuturesPositions(symbolOrderConfig.symbol);
          data = positions.map(item => {
            return {
              ...item,
              symbol: item.symbol,
              positionAmt: item.positionAmt,
              entryPrice: item.entryPrice,
              unRealizedProfit: item.unRealizedProfit,
              positionSide: item.positionSide,
            }
          })
  
        } else if (symbolOrderConfig.trade_type === 'delivery') {
          const positions = await exchangeTrader.getDeliverysPositions(symbolOrderConfig.symbol);
          data = positions.map(item => {
            return {
              ...item,
              symbol: item.symbol,
              // positionAmt: item.positionAmt,
              positionAmt: autoToFixed(binanceCommon.countToBaseSymbolCount(symbolOrderConfig.symbol, item.entryPrice, item.positionAmt)) ?? 0,
              entryPrice: item.entryPrice,
              unRealizedProfit: item.unRealizedProfit,
              positionSide: item.positionSide,
            }
          })
       }
       ctx.sendSuccess({ data: data });
       exchangeTrader.destroy();
       return
      } else {
        ctx.sendError({ message: `暂不支持 ${exchangeAccount.exchange}` });
      }
    } catch (error) {
      ctx.sendError({ message: error.message });
    }
    
  }
  public static getRiskPositions = async (ctx: AppContext) => {
    const userId = ctx.state.user && ctx.state.user.id;

    try {
      const userTrader = await traderRobot.trader.findUserTrader(userId);
      if (!userTrader) {
        return ctx.sendError({message: `userTrader未找到，或者配置错误 ${userId}`});
      }
      const positionMap = userTrader.riskModel.positionsMap;
      return ctx.sendSuccess({ data: positionMap });
    } catch (error) {
      ctx.sendError({ message: error.message });
    }
    
  }
  
}